package com.liumuxian.exam.service.impl;


import com.liumuxian.exam.dao.ExamPerformanceDao;
import com.liumuxian.exam.dao.ExamPerformanceDataDao;
import com.liumuxian.exam.dao.QuestionDao;
import com.liumuxian.exam.data.ExamInfoVO;
import com.liumuxian.exam.data.ExamPerformanceVO;
import com.liumuxian.exam.data.ExamQuestionVO;
import com.liumuxian.exam.pojo.ExamPerformance;
import com.liumuxian.exam.pojo.ExamPerformanceData;
import com.liumuxian.exam.service.ExamInfoService;
import com.liumuxian.exam.service.ExamPerformanceService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import util.IdWorker;
import util.VagueUtil;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = true)
public class ExamPerformanceServiceImpl  implements ExamPerformanceService {
    @Autowired
    private ExamPerformanceDao examPerformanceDao;
    @Autowired
    private ExamPerformanceDataDao examPerformanceDateDao;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private QuestionDao questionDao;
    @Autowired
    private ExamInfoService examInfoService;
    @Transactional
    public void save(ExamPerformance examPerformance){
        examPerformance.setId(idWorker.nextId()+"");
        examPerformance.setCreatdate(new Date());
        examPerformance.setState(1);
        examPerformanceDao.save(examPerformance);
    }


    @Override
    @Transactional
    public void submit(String epid, List<ExamPerformanceVO> examPerformanceVO) {
        List<ExamPerformanceData> examPerformanceData = new ArrayList<>();
        ExamPerformance examPerformance1 = examPerformanceDao.findById(epid).get();
        ExamInfoVO examInfoVO= examInfoService.findExamQuestion(examPerformance1.getExaminfoid());
        int correct=0;
        int error=0;
        Long totle=0l;
        for (ExamPerformanceVO epd:examPerformanceVO){
            for (ExamQuestionVO q:examInfoVO.getExamInfoVOList()){
                if(epd.getQid().equals(q.getQuestionid())){
                    ExamPerformanceData epd1 = new ExamPerformanceData();
                    if(epd.getResult().equals(q.getAnswer())){
                        epd1.setQuestionid(epd.getQid());
                        epd1.setExamperformanceid(epd.getEpid());
                        epd1.setCreatdate(new Date());
                        epd1.setIsright("1");
                        epd1.setScore(q.getScore());
                        epd1.setState(1);
                        epd1.setResult(epd.getResult());
                        examPerformanceData.add(epd1);
                        totle+=q.getScore();
                        correct++;
                    }else {
                        epd1.setQuestionid(epd.getQid());
                        epd1.setExamperformanceid(epd.getEpid());
                        epd1.setCreatdate(new Date());
                        epd1.setIsright("0");
                        epd1.setScore(0l);
                        epd1.setState(1);
                        epd1.setResult(epd.getResult());
                        examPerformanceData.add(epd1);
                        examPerformanceData.add(epd1);
                        error++;
                    }
                    continue;
                }
            }
        }
        examPerformance1.setScore(totle);
        examPerformance1.setAccuracy(accuracy(correct,examInfoVO.getExamInfoVOList().size(),0));
        examPerformance1.setErrorrate(accuracy(error,examInfoVO.getExamInfoVOList().size(),0));
//去重审核用户名称
        examPerformanceData = examPerformanceData.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ExamPerformanceData::getQuestionid))), ArrayList::new));


        examPerformanceDao.saveAndFlush(examPerformance1);
        examPerformanceDateDao.saveAll(examPerformanceData);

    }
    
    public List<ExamPerformance> findAll(Map map){
        Specification specification = new VagueUtil().createSpecification(map);

        return examPerformanceDao.findAll(specification);
    }
    public ExamPerformance findByIid(String id){
        ExamPerformance examPerformance = examPerformanceDao.findByIdAndState(id,1);
        return toExamPerformance(examPerformance);
    }



    private ExamPerformance toExamPerformance(ExamPerformance examPerformance){
        try {

        Map map1 = new HashMap();
        map1.put("examperformanceid",examPerformance.getId());
        Specification specification1 = new VagueUtil().createSpecification(map1);
        List<ExamPerformanceData> examPerformanceData = examPerformanceDateDao.findAll(specification1);
        examPerformance.setEpdlist(examPerformanceData);

        }catch (Exception e){
            throw new RuntimeException("查询失败！");
        }
        return examPerformance;

    }
    private static String accuracy(double num, double total, int scale){
        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
        //可以设置精确几位小数
        df.setMaximumFractionDigits(scale);
        //模式 例如四舍五入
        df.setRoundingMode(RoundingMode.HALF_UP);
        double accuracy_num = num / total * 100;
        return df.format(accuracy_num)+"%";
    }
    @Transactional
    public void update(ExamPerformance examPerformance){
        ExamPerformance examPerformance1 = examPerformanceDao.findById(examPerformance.getId()).get();
        BeanUtils.copyProperties(examPerformance,examPerformance1);
        examPerformance1.setUpdatedate(new Date());
        examPerformanceDao.saveAndFlush(examPerformance);
    }
    @Transactional
    public void delete(String id){
        ExamPerformance examPerformance = examPerformanceDao.findById(id).get();
        examPerformance.setUpdatedate(new Date());
        examPerformance.setState(0);
        examPerformanceDao.saveAndFlush(examPerformance);
    }
    public ExamPerformance findById(String id){
        return examPerformanceDao.findById(id).get();
    }

    public List<ExamPerformance> findAllGesTate(String id,Integer state) {
        return examPerformanceDao.findAll((Root<ExamPerformance> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) -> {
            List<Predicate> predicateList = new ArrayList<Predicate>();
            if (id != null && !StringUtils.isEmpty(id)) {
                predicateList.add(criteriaBuilder.equal(root.get("id"), id));
            }
            if (state != null && !StringUtils.isEmpty(state)) {
                predicateList.add(criteriaBuilder.ge(root.get("state"), (Number) state));
            }
            return criteriaBuilder.and( predicateList.toArray(new Predicate[predicateList.size()]));
        });
    }

}
